﻿#include <stdlib.h>
#include <Windows.h>
#include <iostream>
#include <string>
#include <GL/glut.h>

using namespace std;

GLuint texture[2];

// Mouse motion
static int rotateBeginX, rotateBeginY;
static int turnX =0, turnY = 0;

void init(void){
	glShadeModel(GL_SMOOTH);
	glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
	glEnable(GL_DEPTH_TEST);

	GLfloat lightKa[] = {.2f, .2f, .2f, 1.0f};  // ambient light
    GLfloat lightKd[] = {.7f, .7f, .7f, 1.0f};  // diffuse light
    GLfloat lightKs[] = {1, 1, 1, 1};           // specular light
    glLightfv(GL_LIGHT0, GL_AMBIENT, lightKa);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightKd);
    glLightfv(GL_LIGHT0, GL_SPECULAR, lightKs);
	float lightPos[4] = {50, 100, 10, 1};
	glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
}

void motion(int x, int y){
	turnX = turnX + (x - rotateBeginX);
	turnY = turnY + (y - rotateBeginY);
	if(0)
		cout << "X: " << turnX << "\t Y: "<< turnY << endl;
	rotateBeginX = x;
	rotateBeginY = y;
	glutPostRedisplay();
}

void mouse(int button, int state, int x, int y){
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
		rotateBeginX = x;
		rotateBeginY = y;
	}
}

void keyboard(unsigned char key, int x, int y){
	switch (key) {
	case 27: exit(0); break;
	default: break;
    }
}

void reshape(int w, int h){
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(40.0, (GLfloat) w / (GLfloat) h, 1.0, 500.0);
	
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(0,0,7, 0,0,0, 0.0f,1.0f,0.0f);
}

void LoadTextureRAW( const char * filename, int wrap )
{
	//GLuint texture[2];
	int width, height;
	BYTE * data;
	FILE * file;

	for(int i=0; i<2; i++){

		// open texture data
		file = fopen( filename, "rb" );
		if ( file == NULL ) return;
		// allocate buffer
		width = 256;
		height = 256;
		data = (BYTE*)malloc( width * height * 3 );
		// read texture data
		fread( data, width * height * 3, 1, file );
		fclose( file );


		glGenTextures( 1, &texture[i] );															// allocate a texture name
		glBindTexture( GL_TEXTURE_2D, texture[i] );												// select our current texture

		glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );							// select modulate to mix texture with color for shading
		glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER ,GL_LINEAR_MIPMAP_NEAREST );		// when texture area is small, bilinear filter the closest MIP map
		glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );						// when texture area is large, bilinear filter the first MIP map
  		glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap ? GL_REPEAT : GL_CLAMP );		// if wrap is true, the texture wraps over at the edges (repeat)
																								//       ... false, the texture ends at the edges (clamp)
		glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap ? GL_REPEAT : GL_CLAMP );
		gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE, data );	// build our texture MIP maps
	
		free( data );	// free buffer
	}

	for(int i=0; i<2; i++)
		cout << "&texture: " << texture[i] << endl;

	//return texture;
}

void draw(){
	//texture = 
		LoadTextureRAW( "texture.raw", TRUE );

	glEnable( GL_TEXTURE_2D );
    glBindTexture( GL_TEXTURE_2D, texture[0] );

	glBegin(GL_TRIANGLES);
		glTexCoord2f(0.0, 0.0);	glVertex3f(-1,-1,1);
		glTexCoord2f(1.0, 0.0);	glVertex3f(1,-1,1);
		glTexCoord2f(0.0, 1.0);	glVertex3f(0,0,0);
	glEnd();

	glBindTexture( GL_TEXTURE_2D, texture[1] );
	glBegin(GL_TRIANGLES);
		glTexCoord2f(0.0, 0.0);		glVertex3f(1,-1,1);
		glTexCoord2f(1.0, 0.0);		glVertex3f(1,-1,-1);
		glTexCoord2f(1.0, 1.0);		glVertex3f(0,0,0);
	glEnd();

	glBegin(GL_TRIANGLES);
		glVertex3f(1,-1,-1);
		glVertex3f(-1,-1,-1);
		glVertex3f(0,0,0);
	glEnd();
	glBegin(GL_TRIANGLES);
		glVertex3f(-1,-1,-1);
		glVertex3f(-1,-1,1);
		glVertex3f(0,0,0);
	glEnd();

	//glDeleteTextures(1, &texture);
	glDisable(GL_TEXTURE_2D);
}

void display(void){
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glPushMatrix();

	glTranslatef(0, 1, 0);
	glRotatef(turnY, 1.0, 0.0, 0.0);
	glRotatef(turnX, 0.0, 1.0, 0.0); 

	//glutSolidTeapot(1.0);

	draw();

	glPopMatrix();
	glutSwapBuffers();
}

int main(int argc, char **argv){

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_DEPTH);
	glutCreateWindow("OpenGL");

	glutKeyboardFunc (keyboard);
	glutReshapeFunc(reshape);
	glutDisplayFunc(display);
	glutMouseFunc(mouse);
	glutMotionFunc(motion);


	init();
	glutMainLoop();
}